﻿using System;
using UnityEngine;

namespace Miao
{
    /// <summary>
    /// 提供对数学运算的实现.
    /// 该类是对 <see cref="Mathf"/> 的高层封装
    /// </summary>
    public static class MathW
    {
        /// <summary>
        /// π
        /// </summary>
        public const float pi = 3.141592654f;
        /// <summary>
        /// 正周期
        /// </summary>
        public const float pi2 = 2 * pi;
        /// <summary>
        /// 角度转弧度
        /// </summary>
        public const float deg2Rad = pi / 180f;
        /// <summary>
        /// 弧度转角度
        /// </summary>
        public const float rad2deg = 180f / pi;

        public static Color ColorRandom()
        {
            Color color = new Color();
            color.r = UnityEngine.Random.Range(0, 1);
            color.g = UnityEngine.Random.Range(0, 1);
            color.b = UnityEngine.Random.Range(0, 1);
            color.a = 1;
            return color;
        }

        /// <summary>
        /// 区间.
        /// 获取一个公差为1的等差数列，其范围为[<paramref name="minValue"/>, <paramref name="maxValue"/>)
        /// </summary>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static int[] Interval(int minValue, int maxValue)
        {
            if (maxValue <= minValue) throw new Exception($"{nameof(MathW)}.{nameof(Interval)}: {nameof(maxValue)} 必须大于 {nameof(minValue)}");
            int length = maxValue - minValue;
            int[] interval = new int[length];
            int index = 0;
            for (int i = minValue; i < maxValue; i++) interval[index++] = i;
            return interval;
        }
        /// <summary>
        /// 舍入到等差数列.
        /// 将一个数 <paramref name="value"/> 舍入到以 <paramref name="d"/> 为公差的等差数列中最接近的数
        /// </summary>
        /// <param name="value"></param>
        /// <param name="d"></param>
        /// <returns></returns>
        public static float RoundToAP(float value, float d)
        {
            int quotient = (int)(value / d);
            float number = quotient * d;
            float remainder = value % d;
            return remainder < d * 0.5f ? number : number + d;
        }

        /// <summary>
        /// 对数.
        /// 求以 常数e 为底, <paramref name="antilog"/> 的对数
        /// 既 自然对数2.3026 的多少次方可以求解到 antilog
        /// </summary>
        /// <param name="antilog"></param>
        /// <returns></returns>
        public static float LogE(float antilog)
        {
            return Mathf.Log(antilog);
        }
        /// <summary>
        /// 对数.
        /// 求以 常数10 为底, <paramref name="antilog"/> 的对数
        /// 既 10 的多少次方可以求解到 antilog
        /// </summary>
        /// <param name="antilog"></param>
        /// <returns></returns>
        public static float Log10(float antilog)
        {
            return Mathf.Log10(antilog);
        }
        /// <summary>
        /// 对数.
        /// 求以<paramref name="baseNumber"/> 为底, <paramref name="antilog"/> 的对数
        ///对数 既我要用{baseNumber}多少次方可以得到{antilog}值。
        /// </summary>
        /// <param name="antilog"></param>
        /// <param name="baseNumber"></param>
        /// <returns></returns>
        public static float Log(float antilog, float baseNumber)
        {
            return Mathf.Log(antilog, baseNumber);
        }

        /// <summary>
        /// 阶乘
        /// 阶乘是一种数学运算，它表示一个正整数和所有小于它的正整数的乘积。比如，5的阶乘，写作5!，等于5×4×3×2×1
        /// </summary>
        /// <param name="naturalNumber"></param>
        /// <returns></returns>
        public static float Factorial(ulong naturalNumber)
        {
            float result = 1f;
            while (naturalNumber > 1) result *= naturalNumber--;
            return result;
        }


        /// <summary>
        /// 平方根
        /// 设y = x*x 其中单个 x 就是根
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static float Sqrt(float Value)
        {
            return Mathf.Sqrt(Value);
        }
        /// <summary>
        /// 对指数e乘方
        /// </summary>
        /// <param name="exponent"></param>
        /// <returns></returns>
        public static float Exp(float exponent)
        {
            return Mathf.Exp(exponent);
        }
        /// <summary>
        /// 乘方
        /// 乘幂，乘方的结果叫做幂(power)，baseNumber的exponent次幂”或“baseNumber的exponent次幂的exponent次方”
        /// </summary>
        /// <param name="baseNumber"></param>
        /// <param name="exponent"></param>
        /// <returns></returns>
        public static float Pow(float baseNumber, float exponent)
        {
            return Mathf.Pow(baseNumber, exponent);
        }

        /// <summary>
        /// 插值.
        /// 以百分比 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中线性取值
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="t"></param>
        /// <param name="ClampTo01"></param>
        /// <returns></returns>
        public static float Lerp(float a, float b, float t)
        {
            return a + (b - a) * t;
        }
        /// <summary>
        /// 插值.
        /// 以百分比 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中线性取值.
        /// 总是将 <paramref name="t"/> 约束在区间 [0, 1] 内
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static float Lerp01(float a, float b, float t)
        {
            if (t < 0f) t = 0f;
            else if (t > 1f) t = 1f;
            return a + (b - a) * t;
        }
        /// <summary>
        /// 平滑阶梯.
        /// 以百分比 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中平滑取值
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static float SmoothStep(float a, float b, float t)
        {
            return a + (b - a) * t * t * (3f - 2f * t);
        }
        /// <summary>
        /// 平滑阶梯.
        /// 以百分比 <paramref name="t"/> 在区间 [<paramref name="a"/>, <paramref name="b"/>] 中平滑取值.
        /// 总是将 <paramref name="t"/> 约束在区间 [0, 1] 内
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static float SmoothStep01(float a, float b, float t)
        {
            if (t < 0f) t = 0f;
            else if (t > 1f) t = 1f;
            return a + (b - a) * t * t * (3f - 2f * t);
        }

        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static int Clamp(int value, int minValue, int maxValue)
        {
            if (maxValue - minValue < 0)
            {
                minValue ^= maxValue;
                maxValue = minValue ^ maxValue;
                minValue ^= maxValue;
            }
            if (value < minValue) return minValue;
            else if (value > maxValue) return maxValue;
            return value;
        }
        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static bool Clamp(ref int value, int minValue, int maxValue)
        {
            if (maxValue - minValue < 0)
            {
                minValue ^= maxValue;
                maxValue = minValue ^ maxValue;
                minValue ^= maxValue;
            }
            bool clamped = false;
            if (value < minValue)
            {
                clamped = true;
                value = minValue;
            }
            else if (value > maxValue)
            {
                clamped = true;
                value = maxValue;
            }
            return clamped;
        }
        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static float Clamp(float value, float minValue, float maxValue)
        {
            if (maxValue - minValue < 0)
            {
                float temp = minValue;
                minValue = maxValue;
                maxValue = temp;
            }
            if (value < minValue) return minValue;
            else if (value > maxValue) return maxValue;
            return value;
        }
        /// <summary>
        /// 约束 <paramref name="value"/> 到区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static bool Clamp(ref float value, float minValue, float maxValue)
        {
            if (maxValue - minValue < 0)
            {
                float temp = minValue;
                minValue = maxValue;
                maxValue = temp;
            }
            bool clamped = false;
            if (value < minValue)
            {
                clamped = true;
                value = minValue;
            }
            else if (value > maxValue)
            {
                clamped = true;
                value = maxValue;
            }
            return clamped;
        }

        /// <summary>
        /// Clamp the <paramref name="value"/> within [0, 1].
        /// </summary>
        public static float Clamp01(float value)
        {
            if (value < 0f) return 0f;
            if (value > 1f) return 1f;
            return value;
        }
        /// <summary>
        /// Clamp <paramref name="value"/> within [0, 1].
        /// </summary>
        /// <returns>If <paramref name="value"/> is successfully Clamp, return true</returns>
        public static bool Clamp01(ref float value)
        {
            if (value < 0f)
            {
                value = 0f;
                return true;
            }
            if (value > 1f)
            {
                value = 1f;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 映射.
        /// 将区间 [<paramref name="minValueBefore"/>, <paramref name="maxValueBefore"/>] 内的值<paramref name="value"/> 映射到区间 [<paramref name="minValueAfter"/>, <paramref name="maxValueAfter"/>]
        /// </summary>
        /// <param name="value">映射值</param>
        /// <param name="minValueBefore">映射前最小值</param>
        /// <param name="maxValueBefore">映射前最大值</param>
        /// <param name="minValueAfter">映射后最小值</param>
        /// <param name="maxValueAfter">映射后最大值</param>
        /// <returns></returns>
        public static float Mapping(float value, float minValueBefore, float maxValueBefore, float minValueAfter, float maxValueAfter)
        {
            if (minValueBefore == maxValueBefore || minValueAfter == maxValueAfter) throw new Exception("映射值不允许相等!");
            return (value - minValueBefore) / (maxValueBefore - minValueBefore) * (maxValueAfter - minValueAfter) + minValueAfter;
        }

        /// <summary>
        /// 取整
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int Integer(float value)
        {
            return (int)value;
        }
        /// <summary>
        /// 向上取整.
        /// 获取大于等于 <paramref name="value"/> 的最小整数
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Ceil(float value)
        {
            int integer = (int)value;
            return integer == value ? integer : integer + 1f;
        }
        /// <summary>
        /// 向下取整.
        /// 获取小于等于 <paramref name="value"/> 的最大整数
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Floor(float value)
        {
            return (float)System.Math.Floor(value);
        }
        /// <summary>
        /// 舍入.
        /// 仅考虑小数点后一位
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int Round(float value)
        {
            return (int)(value + 0.5f);//仅考虑小数点后1位
        }
        public static float Round(float value, int places, bool round = true)
        {
            if (places <= 0) return value;
            //例, 假设 value 是 3.14125, place 为 4,
            //如果 round = true, 则返回四舍五入的结果, 即3.1413;
            //否则返回截断值, 即3.1412;
            if (round) return (float)System.Math.Round(value, places, MidpointRounding.AwayFromZero);//如果四舍五入, 直接返回
            float divisor = Pow(10f, places);
            return (int)(value * divisor) / divisor;
        }
        /// <summary>
        /// 取符号
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Sign(float value)
        {
            return value < 0f ? -1f : 1f;
        }
        /// <summary>
        /// 取符号.
        /// 如果 <paramref name="value"/> 为 true 返回 1; 否则返回 -1
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Sign(bool value)
        {
            return value ? 1f : -1f;
        }
        /// <summary>
        /// 取符号.
        /// 如果 <paramref name="value"/> 为 0, 返回 0
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float SignZero(float value)
        {
            if (value == 0f) return 0f;
            return value < 0f ? -1f : 1f;
        }

        /// <summary>
        /// 绝对值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int Abs(int value)
        {
            return Mathf.Abs(value);
        }
        /// <summary>
        /// 绝对值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Abs(float value)
        {
            return Mathf.Abs(value);
        }

        /// <summary>
        /// 最大值
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static int Max(params int[] values)
        {
            return Mathf.Max(values);
        }
        /// <summary>
        /// 最大值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="value1"></param>
        /// <returns></returns>
        public static int Max(int value, int value1)
        {
            return Mathf.Max(value, value1);
        }
        /// <summary>
        /// 最大值
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static float Max(params float[] values)
        {
            return Mathf.Max(values);
        }
        /// <summary>
        /// 最大值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="value1"></param>
        /// <returns></returns>
        public static float Max(float value, float value1)
        {
            return Mathf.Max(value, value1);
        }

        /// <summary>
        /// 最小值
        /// </summary>
        /// <param name="valus"></param>
        /// <returns></returns>
        public static int Min(params int[] valus)
        {
            return Mathf.Min(valus);
        }
        /// <summary>
        /// 最小值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="value1"></param>
        /// <returns></returns>
        public static int Min(int value, int value1)
        {
            return Mathf.Min(value, value1);
        }
        /// <summary>
        /// 最小值
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static float Min(params float[] values)
        {
            return Mathf.Min(values);
        }
        /// <summary>
        /// 最小值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="value1"></param>
        /// <returns></returns>
        public static float Min(float value, float value1)
        {
            return Mathf.Min(value, value1);
        }

        /// <summary>
        /// 重复.等同于 除余 (%) 但可以用于负数
        /// 求 <paramref name="value"/> 对 <paramref name="length"/> 的余数
        /// </summary>
        /// <param name="value"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static float Repeat(float value, float length)
        {
            return value - Floor(value / length) * length;
        }


        /// <summary>
        /// 逼近目标值，如果已经到了则维持
        /// 将值 <paramref name="current"/> 推进 <paramref name="delta"/> 直到 <paramref name="target"/>
        /// </summary>
        /// <param name="current"></param>
        /// <param name="target"></param>
        /// <param name="delta">每次靠近的值</param>
        /// <returns></returns>
        public static Color MoveTowards(Color current, Color target, Color delta)
        {
            Color color = new Color();
            color.r = MoveTowards(current.r, target.r, delta.r);
            color.g =  MoveTowards(current.g, target.g, delta.g);
            color.b = MoveTowards(current.b, target.b, delta.b);
            color.a = MoveTowards(current.a, current.a, delta.a);
            return color;
        }

        /// <summary>
        /// 逼近目标值，如果已经到了则维持
        /// 将值 <paramref name="current"/> 推进 <paramref name="delta"/> 直到 <paramref name="target"/>
        /// </summary>
        /// <param name="current"></param>
        /// <param name="target"></param>
        /// <param name="delta">每次靠近的值</param>
        /// <returns></returns>
        public static float MoveTowards(float current, float target, float delta)
        {
            float difference = target - current;
            return Abs(difference) <= delta ? target : current + Sign(difference) * delta;
        }
        /// <summary>
        /// 判断角度 <paramref name="angle"/> 与角度 <paramref name="targetAngle"/> 的相对位置.
        /// 角度范围[0f, 360f]
        /// </summary>
        /// <param name="angle"></param>
        /// <param name="targetAngle"></param>
        /// <returns>如果位于左侧, 返回 -1, 位于右侧, 返回 1, 相同返回 0</returns>
        public static float AngleDirection(float angle, float targetAngle)
        {
            return SignZero(DeltaAngle(angle, targetAngle));
        }
        /// <summary>
        /// 获取角度 <paramref name="angle"/> 到 角度<paramref name="targetAngle"/> 的最短差.
        /// 角度范围[0f, 360f]
        /// </summary>
        /// <param name="angle"></param>
        /// <param name="targetAngle"></param>
        /// <returns></returns>
        public static float DeltaAngle(float angle, float targetAngle)
        {
            angle = Repeat(angle - targetAngle, 360f);
            if (angle > 180f) angle -= 360f;
            return angle;
        }
        /// <summary>
        /// 角度校正.
        /// 将范围为 [0f, 360f] 的Unity默认角度 <paramref name="angle"/> 映射到 易于计算的 [-180f, 180f]
        /// </summary>
        /// <param name="angle"></param>
        /// <returns></returns>
        public static float AngleCorrect(float angle)
        {
            if (angle > 180f) angle -= 360f;
            return angle;
        }

        /// <summary>
        /// Sin.
        /// 通过弧度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Sin(float value)
        {
            return Mathf.Sin(value);
        }
        /// <summary>
        /// Cos.
        /// 通过弧度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Cos(float value)
        {
            return Mathf.Cos(value);
        }
        /// <summary>
        /// Cot.
        /// 通过弧度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Cot(float value)
        {
            return 1 / Mathf.Tan(value);
        }
        /// <summary>
        /// Tan.
        /// 通过弧度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Tan(float value)
        {
            return Mathf.Tan(value);
        }

        /// <summary>
        /// Sin.
        /// 通过角度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float SinDeg(float value)
        {
            return Mathf.Sin(value * deg2Rad);
        }
        /// <summary>
        /// Cos.
        /// 通过角度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float CosDeg(float value)
        {
            return Mathf.Cos(value * deg2Rad);
        }
        /// <summary>
        /// Cot.
        /// 通过角度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float CotDeg(float value)
        {
            return 1 / Mathf.Tan(value * deg2Rad);
        }
        /// <summary>
        /// Tan.
        /// 通过角度计算
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float TanDeg(float value)
        {
            return Mathf.Tan(value * deg2Rad);
        }

        /// <summary>
        /// 反sin.
        /// </summary>
        /// <param name="value">sin值</param>
        /// <returns>sin弧度</returns>
        public static float Asin(float value)
        {
            if (!InRange(value, -1f, 1f)) throw new Exception($"{nameof(MathW)}.{nameof(Acos)}: sin值的范围应该在区间 [-1, 1] 内");
            return Mathf.Asin(value);
        }
        /// <summary>
        /// 反cos.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float Acos(float value)
        {
            if (!InRange(value, -1f, 1f)) throw new Exception($"{nameof(MathW)}.{nameof(Acos)}: cos值的范围应该在区间 [-1, 1] 内");
            return Mathf.Acos(value);
        }

        /// <summary>
        /// 将点 <paramref name="position"/> 按照方向 <paramref name="projectionDirection"/> 投影到以平面点 <paramref name="planeOrigin"/> 和平面法线 <paramref name="planeNormal"/> 定义的平面中
        /// </summary>
        /// <param name="projectionPosition">如果返回值为 true, 表示投影点</param>
        /// <returns>是否有投影点</returns>
        public static bool ProjectToPlane(Vector3 position, Vector3 planeOrigin, Vector3 planeNormal, Vector3 projectionDirection, out Vector3 projectionPosition)
        {
            planeNormal.Normalize();
            projectionDirection.Normalize();
            float dot = Vector3.Dot(planeNormal, projectionDirection);
            if (Mathf.Approximately(dot, 0f))//如果点积为0, 说明夹角等于90度, 不可能有投影点
            {
                projectionPosition = Vector3.zero;
                return false;
            }
            float difference = Vector3.Dot(planeOrigin, planeNormal) - Vector3.Dot(position, planeNormal);
            float length = difference / dot;
            projectionPosition = position + projectionDirection * length;
            return true;
        }

        /// <summary>
        /// 点 <paramref name="position"/> 是否在三角形内.
        /// 三角形位于xz平面, <paramref name="height"/> 为y轴
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">三角形角度</param>
        /// <param name="length">三角形长度</param>
        /// <returns></returns>
        public static bool IsInTriangle(Transform transform, Vector3 position, float angle, float length)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPoint = worldToLocalMatrix.MultiplyPoint(position);
            if (localPoint.z > length) return false;
            localPoint.y = 0;
            if (Vector3.Angle(localPoint.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }
        /// <summary>
        /// 点 <paramref name="position"/> 是否在三角形内.
        /// 三角形位于xz平面, <paramref name="height"/> 为y轴
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">三角形角度</param>
        /// <param name="length">三角形长度</param>
        /// <param name="height">三角形的高度</param>
        /// <returns></returns>
        public static bool IsInTriangle(Transform transform, Vector3 position, float angle, float length, float height)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPoint = worldToLocalMatrix.MultiplyPoint(position);
            if (Abs(localPoint.y) > height * 0.5f) return false;
            if (localPoint.z > length) return false;
            localPoint.y = 0;
            if (Vector3.Angle(localPoint.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }

        /// <summary>
        /// 点 <paramref name="position"/> 是否在扇形内.
        /// 该扇形位于xz平面
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">扇形的角度</param>
        /// <param name="sideLength">扇形的边长</param>
        /// <param name="height">扇形的高度</param>
        /// <returns></returns>
        public static bool IsInSector(Transform transform, Vector3 position, float angle, float sideLength)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (localPosition.sqrMagnitude > sideLength * sideLength) return false;
            localPosition.y = 0;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }
        /// <summary>
        /// 点 <paramref name="position"/> 是否在扇形内.
        /// 该扇形位于xz平面, <paramref name="height"/> 为y轴
        /// </summary>
        /// <param name="transform">Unity Transform 组件</param>
        /// <param name="position">判断点</param>
        /// <param name="angle">扇形的角度</param>
        /// <param name="sideLength">扇形的边长</param>
        /// <param name="height">扇形的高度</param>
        /// <returns></returns>
        public static bool IsInSector(Transform transform, Vector3 position, float angle, float sideLength, float height)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (Abs(localPosition.y) > height * 0.5f) return false;
            if (localPosition.sqrMagnitude > sideLength * sideLength) return false;
            localPosition.y = 0;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }

        /// <summary>
        /// 点 <paramref name="position"/> 是否在球锥内
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="position">判断点</param>
        /// <param name="angle">球锥的角度</param>
        /// <param name="sideLength">球锥的边长</param>
        /// <returns></returns>
        public static bool IsInBallCone(Transform transform, Vector3 position, float angle, float sideLength)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (localPosition.sqrMagnitude > sideLength * sideLength) return false;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }
        /// <summary>
        /// 点 <paramref name="position"/> 是否在圆锥内
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="position">判断点</param>
        /// <param name="angle">圆锥的角度</param>
        /// <param name="length">圆锥的长度</param>
        /// <returns></returns>
        public static bool IsInCircularCone(Transform transform, Vector3 position, float angle, float length)
        {
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localPosition = worldToLocalMatrix.MultiplyPoint(position);
            if (localPosition.z > length) return false;
            if (Vector3.Angle(localPosition.normalized, Vector3.forward) > angle * 0.5f) return false;
            return true;
        }

        /// <summary>
        /// 判断点 <paramref name="position"/> 是否位于相机 <paramref name="camera"/> 视锥体内
        /// </summary>
        /// <param name="camera"></param>
        /// <param name="position"></param>
        /// <returns></returns>
        public static bool IsInViewFrustum(Camera camera, Vector3 position)
        {
            Transform transform = camera.transform;
            Matrix4x4 worldToLocalMatrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one).inverse;
            Vector3 localposition = worldToLocalMatrix.MultiplyPoint3x4(position);
            float nearDistance = camera.nearClipPlane;
            float farDistance = camera.farClipPlane;
            float z = localposition.z;
            if (z < nearDistance || z > farDistance) return false;
            float scale = (z - nearDistance) / (farDistance - nearDistance);
            float tan = Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
            float nearHeight = nearDistance * tan;
            float farHeight = farDistance * tan;
            float halfHeight = (farHeight - nearHeight) * scale;
            float y = localposition.y;
            if (y < -halfHeight || y > halfHeight) return false;
            float aspect = camera.aspect;
            float halfWidth = halfHeight * aspect;
            float x = localposition.x;
            if (x < -halfWidth || x > halfWidth) return false;
            return true;
        }
        /// <summary>
        /// 是否在区间 [<paramref name="minValue"/>, <paramref name="maxValue"/>] 内
        /// </summary>
        /// <param name="value"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static bool InRange(float value, float minValue, float maxValue)
        {
            return value <= maxValue && value >= minValue;
        }

        /// <summary>
        /// 是否为素数
        /// 质数(素数)是指大于1并且只能被1和自身整除的自然数
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public static bool IsPrime(int number)
        {
            if (number <= 1) return false;//如果小于等于1，不是质数
            int 平方根 = (int)Sqrt(number);//获取该数的平方根，这是因为除法中总有一个除数在1~平方根的范围内
            for (int i = 2; i <= 平方根; i++) if (number % i == 0) return false;//遍历从2到该数的平方根。如果余数为0，说明能整除，不是质数
            return true;//循环结束后还是不能整除，说明是质数
        }
        /// <summary>
        /// 是否为偶数
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public static bool IsEven(int number)
        {
            return (number & 1) == 0;// 任何偶数的二进制第一位都是0，所以只要是偶数，和1做 逻辑与 处理后，得到的总是0
        }
    }
}